#ifndef SEMANTIC_H
#define SEMANTIC_H

#include "TreeNode.h"
#include "common.h"

typedef enum From_
{
	FROM_VARIABLE,FROM_FIELD,FROM_PARAM
}From;

typedef struct Type_* Type;
typedef struct Structure_* Structure;
typedef struct FieldList_* FieldList;
typedef struct Function_* Function;

struct Type_{
	enum { BASIC,ARRAY,STRUCTURE,FUNCTION } kind;
	union{
		// basic type
		enum { TYPE_INT=255,TYPE_FLOAT }basic;
		
		// array information
		struct { Type elem; int size;} array;
		
		// structure information
		Structure structure;	
		
		// function information
		Function function;
	};	//maybe can also delete u
	enum { LEFT,RIGHT,BOTH } assign;
};

struct Structure_{
	char *name;
	FieldList domain;
};

struct FieldList_{
	// Field name
	char *name;
	// Field type
	Type type;
	// next field
	FieldList tail;
};

struct Function_{
	char *name;
	int isDefined;
	int line;
	Type r_type;
	FieldList param;
};

bool typeEqual(Type lhs, Type rhs);
bool structEqual(Structure lhs, Structure rhs);

void Program(TreeNode* root);
void ExtDefList(TreeNode *n);
void ExtDef(TreeNode *n);
void ExtDecList(TreeNode *n, Type type);

Type Specifier(TreeNode *n);
Type StructSpecifier(TreeNode *n);

FieldList VarDec(TreeNode *n, Type type, From from);
Function FunDec(TreeNode *n, Type type);
FieldList VarList(TreeNode *n);
FieldList ParamDec(TreeNode *n);

void CompSt(TreeNode *n, Function BlngFunc);
void StmtList(TreeNode *n, Function BlngFunc);
void Stmt(TreeNode *n, Function BlngFunc);

FieldList DefList(TreeNode *n, From from);
FieldList Def(TreeNode *n, From from);
FieldList DecList(TreeNode *n, Type type, From from);
FieldList Dec(TreeNode *n, Type type, From from);

Type Exp(TreeNode *n);
bool Args(TreeNode *n, FieldList param);

#endif
